package utils;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtil implements Serializable {

	private static final long serialVersionUID = 1L;

	public final static String DATETIME = "yyyy-MM-dd HH:mm:ss";
	public final static String DATE = "yyyy-MM-dd";
	public final static String TIME = "HH:mm:ss";
	public final static String DATETIMENOSPACE = "yyyyMMddHHmmss";
	public final static String DATENOSPACE = "yyyyMMdd";
	public final static String TIMENOSPACE = "HHmmss";
	public final static String CARDEXPIRE = "yyMM";
	public final static String DATEWITHDOT = "yyyy.MM.dd";

	public static Date parse(String source) {
		return parse(source, DATETIME);
	}

	public static Date parse(String source, String pattern) {
		try {
			return new SimpleDateFormat(pattern).parse(source);
		} catch (Exception e) {
			return null;
		}
	}

	public static String format() {
		return format(new Date(), DATETIME);
	}

	public static String format(Date source) {
		return format(source, DATETIME);
	}

	public static String format(Date source, String pattern) {
		if (source == null) {
			return null;
		}
		return new SimpleDateFormat(pattern).format(source);
	}

	// 是否闰年
	public static boolean leapYear(int year) {
		return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
	}

	// 根据一个日期，返回是星期几的字符串
	public static String weekNumber(Date source) {
		if (source == null) {
			return "";
		}
		Calendar c = Calendar.getInstance();
		c.setTime(source);
		return new SimpleDateFormat("EEEE").format(c.getTime());
	}

	// 取某个日期的00:00:00
	public static Date topOfDay(Date source) {
		try {
			return parse(format(source, DATE) + " 00:00:00", DATETIME);
		} catch (Exception e) {
			return new Date(0L);
		}
	}

	// 取某个日期的23:59:59
	public static Date endOfDay(Date source) {
		if (source == null) {
			return new Date();
		}
		return DateUtil.topOfDay(intervalDay(source, 1));
	}

	// 得到某个日期和现在的间隔天数
	public static Long distanceDays(Date source) {
		return distanceDays(source, new Date());
	}

	// 得到两个日期间的间隔天数
	public static Long distanceDays(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			return null;
		}
		Long day = (date1.getTime() - date2.getTime()) / (24 * 60 * 60 * 1000);
		return Math.abs(day);
	}

	// 返回间距N天的日期
	public static Date intervalDay(int days) {
		return intervalDay(new Date(), days);
	}

	// 返回间距某日期N天的日期
	public static Date intervalDay(Date source, int days) {
		if (source == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(source);
		c.add(Calendar.DATE, days);
		Date date = c.getTime();
		return date;
	}

	// 返回间距N月的日期
	public static Date intervalMonth(int months) {
		return intervalMonth(new Date(), months);
	}

	// 返回间距某月N月的日期
	public static Date intervalMonth(Date source, int months) {
		if (source == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(source);
		c.add(Calendar.MONTH, months);
		Date date = c.getTime();
		return date;
	}

	// 返回间距N年的日期
	public static Date intervalYear(int years) {
		return intervalYear(new Date(), years);
	}

	// 返回间距某年N年的日期
	public static Date intervalYear(Date source, int years) {
		if (source == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(source);
		c.add(Calendar.YEAR, years);
		Date date = c.getTime();
		return date;
	}

	// 获取当月第一天
	public static Date firstDayOfMonth() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DATE, 1);// 设为当前月的1号
		return cal.getTime();
	}

	// 计算当月最后一天,返回字符串
	public static Date lastDayOfMonth() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DATE, 1);// 设为当前月的1号
		cal.add(Calendar.MONTH, 1);// 加一个月，变为下月的1号
		cal.add(Calendar.DATE, -1);// 减去一天，变为当月最后一天
		return cal.getTime();
	}

	// 上月第一天
	public static Date firstDayOfPreviousMonth() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DATE, 1);// 设为当前月的1号
		cal.add(Calendar.MONTH, -1);// 减一个月
		return cal.getTime();
	}

	// 获得上月最后一天的日期
	public static Date lastDayOfPreviousMonth() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DATE, 1);// 设为当前月的1号
		cal.add(Calendar.DATE, -1);// 减一天
		return cal.getTime();
	}

	// 获得下个月第一天的日期
	public static Date firstDayOfNextMonth() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, 1);// 加一个月
		cal.set(Calendar.DATE, 1);// 把日期设置为当月第一天
		return cal.getTime();
	}

	// 获得下个月最后一天的日期
	public static Date lastDayOfNextMonth() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, 2);// 加两个月
		cal.set(Calendar.DATE, 1);// 把日期设置为当月第一天
		cal.add(Calendar.DATE, -1);// 把日期设置为当月第一天
		return cal.getTime();
	}

	// 获取当年第一天
	public static Date firstDayOfYear() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DAY_OF_YEAR, 1);// 设为当前年的1号
		return cal.getTime();
	}

	// 计算当年最后一天,返回字符串
	public static Date lastDayOfYear() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DAY_OF_YEAR, 1);// 设为当前年的1号
		cal.add(Calendar.YEAR, 1);// 加一个年，变为下年的1号
		cal.add(Calendar.DATE, -1);// 减去一天，变为当年最后一天
		return cal.getTime();
	}

	// 上年第一天
	public static Date firstDayOfPreviousYear() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DAY_OF_YEAR, 1);// 设为当前年的1号
		cal.add(Calendar.YEAR, -1);// 减一个年
		return cal.getTime();
	}

	// 获得上年最后一天的日期
	public static Date lastDayOfPreviousYear() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DAY_OF_YEAR, 1);// 设为当前年的1号
		cal.add(Calendar.DATE, -1);// 减一天
		return cal.getTime();
	}

	// 获得下个年第一天的日期
	public static Date firstDayOfNextYear() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.YEAR, 1);// 加一个年
		cal.set(Calendar.DAY_OF_YEAR, 1);// 把日期设置为当年第一天
		return cal.getTime();
	}

	// 获得下个年最后一天的日期
	public static Date lastDayOfNextYear() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.YEAR, 2);// 加两个年
		cal.set(Calendar.DAY_OF_YEAR, 1);// 把日期设置为当年第一天
		cal.add(Calendar.DATE, -1);// 减一天
		return cal.getTime();
	}

	public static void main(String[] args) {
		System.out.println(endOfDay(new Date()));

		System.out.println("是否闰年:" + leapYear(2017));
		System.out.println("根据日期返回周几:" + weekNumber(intervalDay(-1)));

		System.out.println("获取某天的最开始:" + DateUtil.format(DateUtil.topOfDay(intervalDay(-1))));
		System.out.println("获取某天的最结尾:" + DateUtil.format(DateUtil.endOfDay(intervalDay(-1))));
		System.out.println("获取昨天的日期:" + DateUtil.format(intervalDay(-1)));
		System.out.println("获取明天的日期:" + DateUtil.format(intervalDay(1)));
		System.out.println("获取7天后的日期:" + DateUtil.format(intervalDay(7)));
		System.out.println("获取7天前的日期:" + DateUtil.format(intervalDay(-7)));
		System.out.println("获取两个日期间隔的天数:" + distanceDays(intervalDay(2), intervalDay(-16)));

		System.out.println("获取当月第一天日期:" + DateUtil.format(firstDayOfMonth()));
		System.out.println("获取当月最后一天日期:" + DateUtil.format(lastDayOfMonth()));
		System.out.println("获取上个月第一天日期:" + DateUtil.format(firstDayOfPreviousMonth()));
		System.out.println("获取上个月最后一天日期:" + DateUtil.format(lastDayOfPreviousMonth()));
		System.out.println("获取下个月第一天日期:" + DateUtil.format(firstDayOfNextMonth()));
		System.out.println("获取下个月最后一天日期:" + DateUtil.format(lastDayOfNextMonth()));

		System.out.println("获取当年第一天日期:" + DateUtil.format(firstDayOfYear()));
		System.out.println("获取当年最后一天日期:" + DateUtil.format(lastDayOfYear()));
		System.out.println("获取上个年第一天日期:" + DateUtil.format(firstDayOfPreviousYear()));
		System.out.println("获取上个年最后一天日期:" + DateUtil.format(lastDayOfPreviousYear()));
		System.out.println("获取下个年第一天日期:" + DateUtil.format(firstDayOfNextYear()));
		System.out.println("获取下个年最后一天日期:" + DateUtil.format(lastDayOfNextYear()));
	}

}
